package com.hex.ds.hdtp.core.app.script.analyze.handler.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.hex.ds.hdtp.core.app.common.enums.BasicListStatus;
import com.hex.ds.hdtp.core.app.script.analyze.dto.response.ScriptAnalyzeListResponseDto;
import com.hex.ds.hdtp.core.app.script.analyze.handler.IScriptAnalyzeHandlerService;
import com.hex.ds.hdtp.core.app.script.analyze.service.IScriptAnalyzeListService;
import com.hex.ds.hdtp.core.app.script.analyze.service.IScriptAnalyzeTaskService;
import com.hex.ds.hdtp.core.app.script.common.converter.IScriptTableConsanguinityConverter;
import com.hex.ds.hdtp.core.app.script.common.service.IScriptTableConsanguinityService;
import com.hex.ds.hdtp.core.inf.script.analyze.po.ScriptAnalyzeTaskPo;
import com.hex.ds.hdtp.core.inf.script.common.service.IScriptConvertService;
import com.hex.hdtp.scf.basic.convert.entity.ConvertConfig;
import com.hex.hdtp.scf.basic.convert.entity.ConvertResult;
import com.hex.hdtp.scf.basic.convert.entity.ScriptInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Package com.hex.ds.hdtp.core.app.script.analyze.handler.impl
 * @ClassName ScriptAnalyzeHandlerService
 * @Description 脚本分析业务处理
 * @Author gj.xu
 * @Date 2023/12/8 18:22
 * @Version v2.0
 **/
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy, @Autowired})
public class ScriptAnalyzeHandlerService implements IScriptAnalyzeHandlerService {

    private final IScriptConvertService scriptConvertService;

    private final IScriptAnalyzeListService scriptAnalyzeListService;

    private final IScriptAnalyzeTaskService scriptAnalyzeTaskService;

    private final IScriptTableConsanguinityConverter scriptTableConsanguinityConverter;

    private final IScriptTableConsanguinityService scriptTableConsanguinityService;

    @Override
    @Async("scriptAnalyzeAsyncTaskExecutor")
    public void scriptAnalyzeHandler(ScriptAnalyzeListResponseDto scriptAnalyzeList, ScriptAnalyzeTaskPo scriptAnalyzeTask) {
        log.info("脚本【{}】开始分析，开始时间:{}", scriptAnalyzeList.getSourceFileName(), DateUtil.now());
        modifyAnalyzeListStatusById(scriptAnalyzeList.getPkId(), BasicListStatus.PROCESSING.name(), null);
        try {
            ConvertConfig convertConfig = new ConvertConfig();
            convertConfig.setSourceFilePath(scriptAnalyzeList.getSourceFileAbsolutePath());
            ConvertResult convertResult = scriptConvertService.scriptAnalyze(scriptAnalyzeTask.getAnalyzeType(), convertConfig);
            // 判断分析是否成功
            if (isAnalyzeSuccess(convertResult)) {
                analyzeSuccessHandler(scriptAnalyzeTask, scriptAnalyzeList, convertResult);
            }
        } catch (Exception e) {
            log.error("脚本【{}】分析失败，失败原因:{}", scriptAnalyzeList.getSourceFileName(), e.getMessage(), e);
            analyzeFailHandler(scriptAnalyzeTask.getPkId(), scriptAnalyzeList.getPkId(), e.getMessage());
        } finally {
            log.info("脚本【{}】结束分析，结束时间:{}", scriptAnalyzeList.getSourceFileName(), DateUtil.now());
        }
    }

    @Override
    public List<String> scriptConvertType() {
        return scriptConvertService.scriptConvertType();
    }

    /**
     * @Method modifyAnalyzeListStatusById
     * @Param
     * @Param pkId
     * @Param status
     * @Param log
     * @Return void
     * @Description 更新清单状态
     * @Author gj.xu
     * @Date 2023/12/8 19:53
     * @Version V2.0
     */
    private void modifyAnalyzeListStatusById(String pkId, String status, String log) {
        scriptAnalyzeListService.modifyStatus(pkId, status, log);
        if (BasicListStatus.PROCESSING.name().equals(status)) {
            scriptAnalyzeListService.modifyStartTsById(pkId);
        } else {
            scriptAnalyzeListService.modifyEndTsById(pkId);
        }
    }

    /**
     * @Method analyzeFailHandler
     * @Param
     * @Param analyzeTaskPkId
     * @Param analyzeListPkId
     * @Param message
     * @Return void
     * @Description 分析脚本失败时处理
     * @Author gj.xu
     * @Date 2023/12/9 16:00
     * @Version V2.0
     */
    private void analyzeFailHandler(String analyzeTaskPkId, String analyzeListPkId, String message) {
        modifyAnalyzeListStatusById(analyzeListPkId, BasicListStatus.FAIL.name(), message);
        scriptAnalyzeTaskService.modifyFailCount(analyzeTaskPkId);
    }


    /**
     * @Method analyzeSuccessHandler
     * @Param
     * @Param scriptAnalyzeTask
     * @Param scriptAnalyzeList
     * @Param convertResult
     * @Return void
     * @Description 分析脚本成功时处理
     * @Author gj.xu
     * @Date 2023/12/9 16:00
     * @Version V2.0
     */
    private void analyzeSuccessHandler(ScriptAnalyzeTaskPo scriptAnalyzeTask, ScriptAnalyzeListResponseDto scriptAnalyzeList, ConvertResult convertResult) {
        modifyAnalyzeListStatusById(scriptAnalyzeList.getPkId(), BasicListStatus.SUCCESS.name(), null);
        // 添加各脚本对应的血缘
        addTableConsanguinity(scriptAnalyzeList, convertResult);
        scriptAnalyzeTaskService.modifySuccessCount(scriptAnalyzeList.getAnalyzeTaskPkId());
    }

    /**
     * @Method addTableConsanguinity
     * @Param
     * @Param scriptAnalyzeList
     * @Param convertResult
     * @Return void
     * @Description 添加各脚本对应的血缘
     * @Author gj.xu
     * @Date 2023/12/10 17:26
     * @Version V2.0
     */
    private void addTableConsanguinity(ScriptAnalyzeListResponseDto scriptAnalyzeList, ConvertResult convertResult) {
        for (ScriptInfo scriptInfo : convertResult.getScriptInfos()) {
            if (CollectionUtil.isNotEmpty(scriptInfo.getOrigSrcTableContent())) {
                for (String tableName : scriptInfo.getOrigSrcTableContent()) {
                    scriptTableConsanguinityService.add(scriptTableConsanguinityConverter.toScriptAnalyzeTableConsanguinityForSource(scriptAnalyzeList, tableName));
                }
            }
            if (CollectionUtil.isNotEmpty(scriptInfo.getOrigTargetTableContent())) {
                for (String tableName : scriptInfo.getOrigTargetTableContent()) {
                    scriptTableConsanguinityService.add(scriptTableConsanguinityConverter.toScriptAnalyzeTableConsanguinityForTarget(scriptAnalyzeList, tableName));
                }
            }
        }
    }

    private boolean isAnalyzeSuccess(ConvertResult convertResult) {
        if (ConvertResult.RESPONSE_CODE.CENTER_500.getCode() == convertResult.getCode()) {
            throw new RuntimeException("分析失败," + convertResult.getMsg());
        }
        return true;
    }
}
